#include "rec_read.h"
#include "cross_com.h"
#include "media_frame_hd.h"
#include "rec_data_io.h"

CRecordReader::CRecordReader(int clientID,int channel)
{
	m_channel    = channel;
	m_clientID   = clientID;

}

CRecordReader::~CRecordReader()
{

}

int CRecordReader::Open(const char * fileName, uint32_t fileIndex,int64_t startTime,int64_t endTime,bool bClearBuf)
{
	int ret = 0;
	ret = OpenSerialFile(fileName,fileIndex);
	if(ret < 0)
	{
		TRACE_ERR("Open fileIndex %d ret %d \n",fileIndex,ret);
		return ret;
	}

	ret = ReadRecInfo();
	if(ret < 0)
	{
		TRACE_ERR("Read record info ret %d \n",ret);
		return ret;
	}

	m_curPos = STFS_REC_DATA_OFFSET;
	Seek(m_curPos);
	m_curIndex    = 0;

	//存在时间的话，先去定位相应的关键帧位置　
	if(startTime)
	{
		m_startTime = startTime;
		SeekToTime(startTime,false);
	}

	if(endTime)
	{
		m_endTime = endTime;
	}

	m_pFIFO->Open(m_channel,SIZE_512KB);
	m_pFIFO->SetFileOffsset(m_curPos);
	m_modeLock.Lock();
	if(bClearBuf)
	{
		m_pFIFO->reset(m_curPos);
	}
	m_fileIdx  = fileIndex;
	m_curTime  = startTime;

	g_rec_dataIO.AddReaderTask(m_pFile->get_device_name(), GetLoopLBA(),this);
	m_fileStartLBA = GetLoopLBA();
	//定位到第一帧数据位置
	m_modeLock.UnLock();

	m_bDataEnd = false;
	//TRACE("CLientID%d CH%02d file index %d.Open OK status %s mode %d speed %d\n",
	//			channel, m_fileIdx,(m_fileStatus == STFS_REC_WRITTING)?"Writting":"NORMAL",m_playMode,m_speed);

	return 0;
}
bool   CRecordReader::IsLastFrame()
{
	if(m_lastReadTime >= m_endTime)
	{
		return true;
	}

	return false;
}
int CRecordReader::ReadFrame(uchar_t* frameBuf, uint32_t bufLen)
{
	int ret = 0;
	uint32_t frameSize = 0;
#ifdef _WIN32
	int wait_count = 300;
#else
	int wait_count = 3000;
#endif
	uint32_t data_space = 0;
	uint32_t frmNo = 0;
	uint32_t curFrmNo = 0;
	uint8_t  frameType = 0;
	uchar_t * pMixBuf = NULL;
	//由底层，来智能读取缓冲数据
	if( NULL == m_pFile)
	{
		return ERR_FILE_NOOPEN;
	}
	if( m_bDataEnd &&
		0 == m_pFIFO->GetDataSize())
	{
		return ERR_REPLAY_NODATA;
	}

	for(int idx = 0 ; idx < 3; idx++)
	{
		frameSize = ret = m_pFIFO->GetFrame(frameBuf + BASE_FRAME_HEAD_LEN - 8,bufLen);

		if(ret > 0)
		{
			m_frmTool.Init(frameBuf);
			frameType =m_frmTool.GetFrameType();
			break;
		}
		//剩余空间不足会等待

		while(wait_count)
		{
			if(wait_count == 0)
			{
				TRACE("CH %02d Wait time too long,data space %u ret %d  \n",m_channel,data_space,ret);
				PrintTimeMs(m_curTime,0,"last Frame Time");
				return FIFO_ERR_TIMEOUT;
			}

			CrossSleep(10);
			data_space = m_pFIFO->GetCurWarter();
			if((data_space >= 30))
			{
				//TRACE_ERR("CH %02d FIFO_ERR_NOTENOUGH data_space %d data_size %d wait_count %d \n",m_channel,data_space,data_size,wait_count);
				break;
			}
			wait_count--;
		}

		if(wait_count == 0 && idx == 2)
		{
			TRACE_ERR("CH %02d Wait time too long.data water %u\n",m_channel,data_space);
			m_bDataEnd = true;
			PrintTimeMs(m_curTime,0,"last Frame Time");
			return FIFO_ERR_TIMEOUT;
		}
	}

	//是否混合音频
	if(CRecordReader::MIX_AUDIO  && frameSize > 0)
	{
		LHN_FRAME_H * pFrmHead = (LHN_FRAME_H*)frameBuf;
		uchar_t audioBuf[256] = {0};
		
		TRACE_ERR("MIX_AUDIO %d frameSize %d.\n",CRecordReader::MIX_AUDIO,frameSize );

		m_frmTool.Init(frameBuf);
	

		frameType = m_pFIFO->GetNextFrameType();
		if( AFrame == frameType )
		{   //确保下一帧数据是音频再进行混合

			pMixBuf = frameBuf + BASE_FRAME_HEAD_LEN + pFrmHead->dataLen;
			//将音频混合在视频一起
			//是否转换
			ret = m_pFIFO->GetFrame(audioBuf,256);
			if(ret > 0)
			{
				memcpy(pMixBuf,audioBuf + BASE_FRAME_HEAD_LEN,80);
				pFrmHead->isHaveAudio = true;
				pFrmHead->audioLen    = 80;
				//convert_asf_to_rtp_frame(audioBuf,pMixBuf,pFrmHead->audioLen);
			}
			else
			{
				pFrmHead->isHaveAudio = 0;
				pFrmHead->audioLen    = 0;
			}
		}
	}

// 	m_frmTool.Init(frameBuf);
// 	if(!m_frmTool.IsEffect())
// 	{
// 		PrintTimeMs(m_curTime,0,"last Frame Time");
// 		return ERR_FRAME_HDFLAG;
// 	}

	if(m_endTime != 0)
	{
		m_curTime = m_frmTool.GetFrameTime();
		if( REPLAY_NORMAL == m_playMode)
		{
			if( m_curTime  > m_endTime)//时间超过了录像段的结束时间
			{
				TRACE_ERR("Time  Over file end. cur offset %d.\n",m_curPos);
				PrintTimeMs(m_curTime,0,"cur Time");
				PrintTimeMs(m_endTime,0,"last Frame Time");
				PrintTimeMs(m_startTime,0,"start Time");
				return ERR_FRAME_HDFLAG;
			}
		}
    }

	frameType = m_frmTool.GetFrameType();
	m_curTime    = m_frmTool.GetFrameTime();
	curFrmNo     =  m_frmTool.GetFrameNo();

	if( IFrame == frameType && 0 == m_firtFrmNo )
	{
		m_firtFrmNo = curFrmNo;
	}
	m_lastReadTime = m_frmTool.GetFrameTime();
	frmNo = curFrmNo - m_firtFrmNo;
	m_frmTool.SetFrmNo(frmNo);
	if(frameSize < 0)
	{
		TRACE_ERR("MIX_AUDIO %d frameSize %d.\n",CRecordReader::MIX_AUDIO,frameSize );
	}
	return frameSize;
}

//两倍速快进的思想
/*
  1. 间隔3帧数据 试过间隔2时，可能出现花屏。
  2. I帧不会跳掉
*/
int CRecordReader::ReadFIFO2Forward()
{
	int ret = 0;

	//TRACE("Read To FIFO 2Forward curoffset %d \n",m_cur_offset);

	uint32_t read_size = m_pFIFO->GetFreeSize();
	uint32_t frmSize   = 0;
	uint32_t oneFrmLen = 0;	//单帧数据长度
	uint32_t leaf_data = m_fileLen - m_curPos;// m_fileSize - m_cur_offset;
	if(read_size > leaf_data)
	{
		read_size = leaf_data;
	}
	uchar_t * transBuf = g_rec_dataIO.GetRpBuf(m_pFile->get_device_name());
	CROSS_ASSERT(transBuf != NULL);

	uint32_t  bufSize  = g_rec_dataIO.GetRpBufSize(m_pFile->get_device_name());
	uint32_t  bufOffset= 0;
	FsFrame_t* pFrm    = NULL;
	uchar_t * frmBuf   = NULL;
	int		  step     = 0;
	int64_t  timeBak   = 0;
	uint32_t readSize  = bufSize;
	//循环读取数据到FIFO缓冲当中

	while((frmSize + FRM_HEAD_LEN)< read_size)
	{
		//读取数据到缓冲当中
		leaf_data = m_fileLen - m_curPos;
		if(leaf_data < bufSize)
		{
			readSize = leaf_data;
		}
		else
		{
			readSize = bufSize;
		}

		ret = ReadPos(m_curPos,transBuf,readSize);
		if(ret < 0)
		{
		   TRACE_ERR(" CH%02d pos %d Read data Error.\n",m_channel,m_curPos);
		   goto	ERR_REC;
		}

		//挑取数据
		bufOffset = 0;
		while((bufOffset + FRM_HEAD_LEN)< bufSize)
		{
		    m_frmTool.Init(transBuf + bufOffset);
			if(!m_frmTool.IsEffect())
			{
				bufOffset += 1;
				while(bufOffset < bufSize)
				{
					//pFrm    = (FsFrame_t*)(transBuf + bufOffset);
					 m_frmTool.Init(transBuf + bufOffset);
					//if(pFrm->frameTag == FSFrameTag)
					if(!m_frmTool.IsEffect())
					{
						break;
					}
					bufOffset += 1;
				}
			}

			if(!m_frmTool.IsEffect())
			{
				TRACE_ERR("Error data flag %d.\n",pFrm->frameTag);
				goto ERR_REC;
			}

			//frmBuf  = (uchar_t*)(transBuf + bufOffset);
			m_frmTool.Init(transBuf + bufOffset);
			int64_t frmTime = m_frmTool.GetFrameTime();
			int     frmType = m_frmTool.GetFrameType();
			oneFrmLen = m_frmTool.GetFrameLen(); //dataLen + FRM_HEAD_LEN ;
			if((bufOffset + oneFrmLen) > bufSize)
			{
				break;
			}
			//满足两个条件即可写入到缓冲当中
			//1.间隔2帧数据
			//2.I帧数据强制写入
			if((m_curPos + oneFrmLen)> m_fileLen)
			{
				m_bDataEnd = true;
				goto FILL_END;
			}

			//如果时间超出结束时间，应该立即结束读取数据
			if(pFrm->time > m_endTime)
			{
				m_bDataEnd = true;
				goto FILL_END;
			}

			//支持MJ 快进两倍速，跳帧处理
			if( frmType == PFrame ||
				frmType == MFrame)
			{
				step++;
			}

			if((step ==3 ) || (frmType == IFrame))
			{
				step = 0;
				if(frmTime < timeBak)
				{
					TRACE_ERR("Time Error.\n");
				}

				ret = m_pFIFO->write(frmBuf,oneFrmLen);

				if( ERR_FIFO_NOTENOUGH == ret)
				{
					//TRACE_ERR("Full data.\n");
					goto FILL_END;
				}

				timeBak = frmTime;
				frmSize   += oneFrmLen ;
			}
			bufOffset += oneFrmLen;
			m_curPos += oneFrmLen;

		}

	}

FILL_END:
//	TRACE("CH%02d Read To FIFO  end curoffset %d \n",m_channel,m_curPos);
	return 0;

ERR_REC:
	TRACE("ClientID %02d CH%02d Read To FIFO  end curoffset %d \n",m_clientID,m_channel,m_curPos);
	m_bDataEnd = true;
	return ret;
}

//带有校正偏移的函数
int CRecordReader::ReadFIFOForward()	//只读取关键帧数据,具有跳帧处理
{
	int ret = 0;
	//	TRACE("CH%02d fileIndex %d ReadFIFOForward begin index %02d",m_channel,m_fileIdx,m_curIndex);
	unsigned char* pbuf = NULL;
	uint32_t readBufSize = m_pFIFO->GetFreeSize();
	uint32_t offset    = 0;
	uint32_t frmSize   = 0;
	uint32_t dataSize  = 0;
	int		 frmCount  = 0;
	int		 nexIdx    = 0;
	FsFrame_t * pHd    = NULL;
	pbuf = g_rec_dataIO.GetRpBuf(m_pFile->get_device_name());
	CROSS_ASSERT(pbuf != NULL);
	pHd = (FsFrame_t *)pbuf;
	uint32_t endTime   = (uint32_t)(m_endTime /1000); 
	while(dataSize + FRM_HEAD_LEN < readBufSize )
	{
		nexIdx = m_curIndex + m_stepIFrame;
		if((nexIdx) >= m_maxIndex)
		{
			ret = ERR_REPLAY_BUFFULL;
			m_bDataEnd = true;
			break;
		}

		//增加时间结束判断 尽量不超录像段的时候
		if(m_pIdxBuf[nexIdx].tmMS > endTime)
		{
			//	TRACE("CH%02d 1-2 Over buffer size.Last idx %d\n",m_channel,nexIdx);//Test Info
			ret = ERR_REPLAY_BUFFULL;
			m_bDataEnd = true;
			break;
		}

		offset = m_pIdxBuf[nexIdx].offset;
		frmSize= m_pIdxBuf[nexIdx].frameLen;
		if(frmSize & 0x01)  //进行偶数字节对齐写入到缓冲当中
		{
			frmSize += 1;
		}
		if((dataSize + frmSize) > readBufSize )
		{
			break;
		}

		ret = ReadPos(offset,pbuf,frmSize);
		if(ret < 0)
		{
			TRACE_ERR("CH%02d Read data error offset %d ,size %d. ret %d \n",m_channel,offset,frmSize, ret);
			goto ERR_REC;
		}

		ret = m_pFIFO->write(( uchar_t* )pbuf,frmSize);
		if( ret < 0)
		{
			break;
		}

		m_curIndex += m_stepIFrame;
		dataSize += frmSize;
		frmCount++;
	}

	m_curPos = offset;	//记录最后的Offset

	return frmCount;

ERR_REC:
	m_curPos = offset;
	m_bDataEnd = true;
	dataSize = m_pFIFO->GetDataSize();
	TRACE_ERR("Read data error . ret %d dataSize %d.\n",ret,dataSize);
	return ret;
}

int CRecordReader::ReadFIFOReback()	//逆向读取关键帧数
{
	int ret = 0;
	//TRACE("CH%02d fileIndex %d ReadFIFOForward begin index %02d",m_channel,m_fileIdx,m_curIndex);
	unsigned char* pbuf = NULL;
	uint32_t readBufSize = m_pFIFO->GetFreeSize();

	uint32_t offset    = 0;
	uint32_t frmSize   = 0;
	uint32_t dataSize  = 0;
	int		 frmCount  = 0;
	int		 nexIdx    = 0;
	pbuf = g_rec_dataIO.GetRpBuf(m_pFile->get_device_name());
	CROSS_ASSERT(pbuf != NULL);

	while(dataSize + FRM_HEAD_LEN < readBufSize )
	{
		nexIdx = m_curIndex - m_stepIFrame;
		if((nexIdx) < 0)
		{
			PrintTimeMs(m_startTime,0,"startSec");
			ret = ERR_REPLAY_BUFFULL;
			m_bDataEnd = true;
			break;
		}

		//增加时间结束判断 尽量不超录像段的时候
		if(m_pIdxBuf[nexIdx].tmMS < m_startTime)
		{
			//	TRACE("CH%02d 1-2 Over buffer size.Last idx %d\n",m_channel,nexIdx);//Test Info
			PrintTimeMs(m_pIdxBuf[nexIdx].tmMS,0,"cur IFrm Time");
			PrintTimeMs(m_startTime,0,"startSec");
			ret = ERR_REPLAY_BUFFULL;
			m_bDataEnd = true;
			break;
		}

		offset  = m_pIdxBuf[nexIdx].offset;
		frmSize = m_pIdxBuf[nexIdx].frameLen;
		if(frmSize & 0x01)  //进行偶数字节对齐写入到缓冲当中
		{
			frmSize += 1;
		}
		if((dataSize + frmSize) > readBufSize )
		{
			break;
		}
		ret = ReadPos(offset,pbuf,frmSize);
		if(ret < 0)
		{
			TRACE_ERR("CH%02d Read data error offset %d ,size %d. ret %d \n",m_channel,offset,frmSize, ret);
			goto ERR_REC;
		}

// 		if(!CheckFrame(pbuf,m_pIdxBuf[nexIdx].time,(frmSize - FRM_HEAD_LEN)))
// 		{
// 			ret = CorrectPos(m_pIdxBuf[nexIdx],pbuf,RP_ALIGNBUF_SIZE);
// 			if(ret < 0)
// 			{
// 			//	goto ERR_REC;
// 			}
// 			//CROSS_ASSERT(false);
// 			break;
// 		}

		ret = m_pFIFO->write((uchar_t* )pbuf,frmSize);
		if( ret < 0)
		{
			break;
		}

		m_curIndex -= m_stepIFrame;
		dataSize   += frmSize;
		frmCount++;
	}

	m_curPos = offset;	//记录最后的Offset
	return frmCount;

ERR_REC:
	m_curPos   = offset;
	m_bDataEnd = true;
	TRACE_ERR("Read data error . ret %d .\n",ret);
	return ret;
}

int CRecordReader::ReadFIFONormal()
{
	int ret = ReadRecordData();
	return ret ;
}
